#pragma once
#include <string>
#include <sstream>
#include <vector>	//split string.
#include <map>

/**
 * to exclude the winsock.h in windows.h file
 */
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif

#include "common.h"
#include <mythread.hxx>

#define CAN_RE_REQUEST(retcode)	(\
	(retcode == 1	/* CURLE_UNSUPPORTED_PROTOCOL (1) local socket send error.*/	\
	|| retcode == 52	/* CURLE_GOT_NOTHING (52). */ \
	/*|| retcode == CURLE_COULDNT_CONNECT\ (7)*/\
	/*|| retcode == CURLE_FTP_WEIRD_SERVER_REPLY (8)*/\
	|| retcode == 55 /*CURLE_SEND_ERROR (55) */\
	|| retcode == 56 /* CURLE_RECV_ERROR (56) */\
	|| retcode == 28 /*CURLE_OPERATION_TIMEDOUT (28)*/\
	|| retcode == 404		/* 404 Page Not Found, just refresh/reload it.*/ \
	|| retcode == 408		/* 408 (HTTP Request timeout).*/ \
	/*|| retcode == 503*/	/* 503 too busy server, Application Queue exeeds appRequestQueueLimit. Or Service Unavailable. */ \
	|| retcode == 504))		/* X_WAS_RSPC_GATEWAY_TIMEOUT should retry at grapping */

typedef void CURL;
typedef void CURLSH;
class Mutex;

namespace Util
{
	using std::string;
	using std::stringstream;

	/************************************************************************
	* Constant variables.
	*************************************************************************/
	EXPORT extern const string UserAgent;

	/************************************************************************
	** definition data types.
	*************************************************************************/
	class EXPORT Lock
	{
	public:
		Lock(Mutex* mutex1);
		~Lock();
	private:
		Mutex* mutex;
	};

	void SetShareHandle(CURL* curl);
	void SetHeaders(CURL* curl);
	EXPORT int PerformStepInternal(CURL* curl, const string& url, const string& dataFields, stringstream& bodystream);
	EXPORT CURL* NewCURL(string proxy = "", CURLSH* share = NULL);
	EXPORT CURLSH* NewShareCURL(CURL* seed);
	EXPORT void SetShareCURL(CURL* curl, CURLSH* curlSH);
	EXPORT CURL* NewSrvCURL(void);
	EXPORT string GetEffectivePage(CURL* curl, bool full=false);
	EXPORT void SetReferer(CURL* curl, string referer);
	EXPORT void CleanupCurl(CURL* curl);
	EXPORT void CleanupCurlSH(CURLSH* curlSH);

	EXPORT string EscapeStr(const char* str);
	EXPORT string EscapeStr(const string& str);

    EXPORT size_t write_data(char *ptr, size_t size, size_t nmemb, void *userdata);
	EXPORT string GetMajorError(const std::stringstream& bodystream);
	EXPORT bool FileContain(std::stringstream& bodystream, const string& str, int tellg = 0);
	EXPORT bool FileContainAny(std::stringstream& bodystream, const std::vector<string>& strs, int tellg = 0);
	EXPORT string ExtractField(const std::stringstream& bodystream, const string& start, const string& end, int tellg = 0);
	EXPORT string ExtractInnerText(const std::stringstream& bodystream, const string& id, int tellg = 0);
	EXPORT bool ExtractFields(const std::stringstream& bodystream, const string& start, const string& end, std::vector<string>& fields, int tellg = 0);
	EXPORT bool ExtractSelectOptions(const std::stringstream& bodystream, const string& start, std::map<string, string>& options);

	EXPORT bool ExtractTable(const std::stringstream& bodystream, const string& tableName, std::vector<string>& items);

	EXPORT string GetCTime(void);

	EXPORT std::vector<string> &Split(const string &s, char delim, std::vector<string> &elems);
	EXPORT std::vector<string> Split(const string &s, char delim);
	EXPORT std::string Join(const std::vector<string> &elems, char delim);

	// will cause g++ internal error due to template expansion comsumes lots of memory.
	EXPORT std::string& Trim(string& s);

	EXPORT string Replace(string& str, const string& target, const string& repl);
	EXPORT string Replace(string& str, char c, char replacement=0);
	EXPORT string SpaceStr(int length);
	EXPORT string Int2Str(int i);

	EXPORT string GetViewState(const std::stringstream& bodystream);
	EXPORT void DumpFile(const std::stringstream& bodystream, string filename, bool isimage = false);
	EXPORT string GetEventValidation(const std::stringstream& bodystream);

	EXPORT int CurlAsErrorId(const string errormsg);
	EXPORT int IsReadyForRead(CURL* curl, int tv);
	EXPORT int IsReadyForWrite(CURL* curl, int tv);
	EXPORT string GetCookie(CURL* curl);

	EXPORT string ConvertUTF8toGB2312(const char* pData, int len);
	EXPORT string ConvertUTF8toGB2312(const string& data);
	EXPORT string ConvertGB2312toUTF8(const char *pData, size_t size);
	EXPORT string ConvertGB2312toUTF8(const string& s);

#ifdef WIN32
	EXPORT int Encode(const string& in, string& out);
	EXPORT int Decode(const string& in, string& out);
	EXPORT int Encode(const char* in, int inlen, char** out);
	EXPORT int Decode(const char* in, int inlen, char** out);

	EXPORT bool String2WString(const char* str,LPWSTR buf,ULONG buflen);
	EXPORT bool WString2String(const wchar_t* str,LPSTR buf,ULONG buflen);
	EXPORT void FormatMessage(DWORD lerror);
	EXPORT int GetUniqueId(void);
	EXPORT string GetRandom(unsigned int ints);
#endif
}
